package emulator.hardware.nmos6502.commands;

import emulator.EmulatorException;
import emulator.hardware.HwByte;
import emulator.hardware.nmos6502.Command;
import emulator.hardware.nmos6502.CommandSet;
import emulator.hardware.nmos6502.Cpu6502;
import emulator.hardware.nmos6502.Flags6502;
import emulator.hardware.nmos6502.Operand;
import emulator.hardware.nmos6502.operands.Absolute;
import emulator.hardware.nmos6502.operands.AbsoluteX;
import emulator.hardware.nmos6502.operands.AbsoluteY;
import emulator.hardware.nmos6502.operands.Immediate;
import emulator.hardware.nmos6502.operands.IndirectX;
import emulator.hardware.nmos6502.operands.IndirectY;
import emulator.hardware.nmos6502.operands.ZeroPage;
import emulator.hardware.nmos6502.operands.ZeroPageX;

/** AND (bitwise AND with accumulator)
 *  
 *  Affects Flags: S Z
 *  
 *  MODE           SYNTAX       HEX LEN TIM
 *  Immediate     AND #$44      $29  2   2
 *  Zero Page     AND $44       $25  2   2
 *  Zero Page,X   AND $44,X     $35  2   3
 *  Absolute      AND $4400     $2D  3   4
 *  Absolute,X    AND $4400,X   $3D  3   4+
 *  Absolute,Y    AND $4400,Y   $39  3   4+
 *  Indirect,X    AND ($44,X)   $21  2   6
 *  Indirect,Y    AND ($44),Y   $31  2   5+
 *  
 *  + add 1 cycle if page boundary crossed
 */
public class AND implements Command {

	@Override
	public void execute(Cpu6502 cpu, Operand operand) throws EmulatorException {
		int accu_old = (int)cpu.getAccu().getNumber();
		Flags6502 flags = cpu.getFlags();
		
		int accu = accu_old & (int)operand.getByte().getNumber();
		
		flags.setNZFromValue(accu);
		
		cpu.setAccu(new HwByte(accu));
		cpu.setFlags(flags);
	}

	@Override
	public String getName() {
		return "AND";
	}

	@Override
	public void register(CommandSet cset) {
		 cset.defineCommand(0x29, this, new Immediate());
		 cset.defineCommand(0x25, this, new ZeroPage());
		 cset.defineCommand(0x35, this, new ZeroPageX());
		 cset.defineCommand(0x2D, this, new Absolute());
		 cset.defineCommand(0x3D, this, new AbsoluteX());
		 cset.defineCommand(0x39, this, new AbsoluteY());
		 cset.defineCommand(0x21, this, new IndirectX());
		 cset.defineCommand(0x31, this, new IndirectY());
	}

}
